package com.zenithmind.version.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.version.mapper.RepositoryMapper;
import com.zenithmind.version.pojo.domain.Repository;
import com.zenithmind.version.pojo.dto.RepositoryCreateDTO;
import com.zenithmind.version.pojo.dto.RepositoryStatisticsDTO;
import com.zenithmind.version.pojo.vo.RepositoryVO;
import com.zenithmind.version.service.RepositoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 仓库服务实现类 - 临时简化版本，解决启动问题
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RepositoryServiceImpl extends ServiceImpl<RepositoryMapper, Repository> implements RepositoryService {

    private final RepositoryMapper repositoryMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RepositoryVO createRepository(RepositoryCreateDTO createDTO) {
        log.info("创建仓库: {}", createDTO.getName());
        
        String currentUserId = UserContext.getUserId();
        String currentUserName = UserContext.getUsername();
        
        Repository repository = new Repository();
        repository.setName(createDTO.getName());
        repository.setDescription(createDTO.getDescription());
        repository.setOwnerId(currentUserId);
        repository.setOwnerName(currentUserName);
        repository.setType(createDTO.getType());
        repository.setStatus(1); // 启用状态
        repository.setDefaultBranch(createDTO.getDefaultBranch());
        repository.setLanguage(createDTO.getLanguage());
        repository.setLastActivityTime(LocalDateTime.now());
        repository.setSortOrder(0);

        // 保存仓库
        boolean saved = save(repository);
        if (!saved) {
            throw new RuntimeException("仓库创建失败");
        }

        log.info("仓库创建成功，ID: {}", repository.getId());
        return convertToVO(repository);
    }

    @Override
    public PageResult<RepositoryVO> getRepositoryPage(Long current, Long size, String ownerId,
                                                     Integer type, Integer status, String keyword) {
        Page<Repository> page = new Page<>(current, size);
        IPage<Repository> repositoryPage = repositoryMapper.selectRepositoryPage(page, ownerId, type, status, keyword);

        List<RepositoryVO> records = new ArrayList<>();
        for (Repository repository : repositoryPage.getRecords()) {
            records.add(convertToVO(repository));
        }

        return new PageResult<>(records, repositoryPage.getTotal(), repositoryPage.getCurrent(), repositoryPage.getSize());
    }

    @Override
    public RepositoryVO getRepositoryById(String id) {
        Repository repository = getById(id);
        if (repository == null) {
            return null;
        }
        
        return convertToVO(repository);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateRepository(String id, RepositoryCreateDTO updateDTO) {
        log.info("更新仓库: {}", id);
        
        Repository repository = getById(id);
        if (repository == null) {
            throw new RuntimeException("仓库不存在");
        }
        
        repository.setName(updateDTO.getName());
        repository.setDescription(updateDTO.getDescription());
        repository.setType(updateDTO.getType());
        repository.setDefaultBranch(updateDTO.getDefaultBranch());
        repository.setLanguage(updateDTO.getLanguage());
        repository.setUpdateTime(LocalDateTime.now());
        
        return updateById(repository);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteRepository(String id) {
        log.info("删除仓库: {}", id);
        return removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RepositoryVO forkRepository(String sourceRepositoryId, String name) {
        log.info("Fork仓库: {} -> {}", sourceRepositoryId, name);
        
        String currentUserId = UserContext.getUserId();
        String currentUserName = UserContext.getUsername();
        
        // 查询源仓库
        Repository sourceRepository = getById(sourceRepositoryId);
        if (sourceRepository == null) {
            throw new RuntimeException("源仓库不存在");
        }
        
        // 检查仓库名称是否已存在
        Repository existingRepository = repositoryMapper.selectByNameAndOwner(name, currentUserId);
        if (existingRepository != null) {
            throw new RuntimeException("仓库名称已存在");
        }

        // 创建Fork仓库
        Repository forkRepository = new Repository();
        BeanUtils.copyProperties(sourceRepository, forkRepository);
        forkRepository.setId(null); // 清空ID，让数据库自动生成
        forkRepository.setName(name);
        forkRepository.setOwnerId(currentUserId);
        forkRepository.setOwnerName(currentUserName);
        // 设置父仓库ID（Fork关系）
        // 注意：这里假设Repository实体有parentId字段，如果没有可以通过其他方式记录Fork关系
        // forkRepository.setParentId(sourceRepositoryId);

        // 可以通过description字段记录Fork关系
        String forkDescription = String.format("Forked from %s/%s",
                sourceRepository.getOwnerName(), sourceRepository.getName());
        if (forkRepository.getDescription() != null && !forkRepository.getDescription().trim().isEmpty()) {
            forkRepository.setDescription(forkRepository.getDescription() + " (" + forkDescription + ")");
        } else {
            forkRepository.setDescription(forkDescription);
        }
        forkRepository.setCreateTime(LocalDateTime.now());
        forkRepository.setUpdateTime(LocalDateTime.now());

        boolean saved = save(forkRepository);
        if (!saved) {
            throw new RuntimeException("Fork仓库失败");
        }

        log.info("Fork仓库成功，ID: {}", forkRepository.getId());
        return convertToVO(forkRepository);
    }

    @Override
    public List<RepositoryVO> getUserRepositories(String userId, Integer type) {
        List<Repository> repositories = repositoryMapper.selectUserRepositories(userId, type);
        List<RepositoryVO> result = new ArrayList<>();
        for (Repository repository : repositories) {
            result.add(convertToVO(repository));
        }
        return result;
    }

    @Override
    public List<RepositoryVO> getPublicRepositories(String keyword, String language, Integer limit) {
        List<Repository> repositories = repositoryMapper.selectPublicRepositories(keyword, language, limit);
        List<RepositoryVO> result = new ArrayList<>();
        for (Repository repository : repositories) {
            result.add(convertToVO(repository));
        }
        return result;
    }

    @Override
    public List<RepositoryVO> searchRepositories(String keyword, Integer type, String language, Integer limit) {
        log.info("搜索仓库: keyword={}, type={}, language={}, limit={}", keyword, type, language, limit);

        // 参数验证
        if (keyword == null || keyword.trim().isEmpty()) {
            return new ArrayList<>();
        }

        // 设置默认限制
        if (limit == null || limit <= 0) {
            limit = 20;
        }

        List<Repository> repositories = repositoryMapper.searchRepositories(keyword.trim(), type, language, limit);
        List<RepositoryVO> result = new ArrayList<>();
        for (Repository repository : repositories) {
            result.add(convertToVO(repository));
        }

        log.info("搜索到 {} 个仓库", result.size());
        return result;
    }

    @Override
    public RepositoryStatisticsDTO getRepositoryStatistics(String ownerId) {
        return repositoryMapper.selectStatistics(ownerId);
    }

    @Override
    public Boolean checkRepositoryNameAvailable(String name, String repositoryId) {
        return !repositoryMapper.existsByNameAndOwner(name, repositoryId, null);
    }

    public Boolean checkRepositoryNameExists(String name, String ownerId, String excludeId) {
        return repositoryMapper.existsByNameAndOwner(name, ownerId, excludeId);
    }

    @Override
    public Boolean archiveRepository(String id) {
        log.info("归档仓库: {}", id);
        Repository repository = getById(id);
        if (repository == null) {
            throw new RuntimeException("仓库不存在");
        }

        // 检查仓库是否已经归档
        if (repository.isArchived()) {
            log.warn("仓库已经处于归档状态: {}", id);
            return true;
        }

        // 设置为归档状态
        repository.setStatus(2); // 2-归档
        repository.setUpdateTime(LocalDateTime.now());

        boolean updated = updateById(repository);
        if (updated) {
            log.info("仓库归档成功: {}", id);
        } else {
            log.error("仓库归档失败: {}", id);
        }

        return updated;
    }

    public Boolean archiveRepository(String id, Boolean isArchived) {
        log.info("设置仓库归档状态: {}, 归档状态: {}", id, isArchived);

        if (isArchived) {
            return archiveRepository(id);
        } else {
            return unarchiveRepository(id);
        }
    }

    public Boolean transferRepository(String id, String newOwnerId) {
        log.info("转移仓库: {}, 新所有者: {}", id, newOwnerId);
        Repository repository = getById(id);
        if (repository == null) {
            throw new RuntimeException("仓库不存在");
        }
        repository.setOwnerId(newOwnerId);
        repository.setUpdateTime(LocalDateTime.now());
        return updateById(repository);
    }

    public Boolean updateRepositorySettings(String id, RepositoryCreateDTO settingsDTO) {
        return updateRepository(id, settingsDTO);
    }

    @Override
    public Boolean unarchiveRepository(String id) {
        log.info("取消归档仓库: {}", id);
        Repository repository = getById(id);
        if (repository == null) {
            throw new RuntimeException("仓库不存在");
        }

        // 检查仓库是否已经是启用状态
        if (repository.isEnabled()) {
            log.warn("仓库已经处于启用状态: {}", id);
            return true;
        }

        // 设置为启用状态
        repository.setStatus(1); // 1-启用
        repository.setUpdateTime(LocalDateTime.now());

        boolean updated = updateById(repository);
        if (updated) {
            log.info("仓库取消归档成功: {}", id);
        } else {
            log.error("仓库取消归档失败: {}", id);
        }

        return updated;
    }

    @Override
    public RepositoryVO getRepositoryByNameAndOwner(String repositoryName, String ownerName) {
        log.info("根据名称和所有者查询仓库: repositoryName={}, ownerName={}", repositoryName, ownerName);

        // 参数验证
        if (repositoryName == null || repositoryName.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库名称不能为空");
        }
        if (ownerName == null || ownerName.trim().isEmpty()) {
            throw new IllegalArgumentException("所有者名称不能为空");
        }

        // 通过ownerName查询ownerId，这里简化处理，实际应该查询用户表
        // 暂时使用ownerName作为ownerId
        Repository repository = repositoryMapper.selectByNameAndOwner(repositoryName.trim(), ownerName.trim());

        if (repository != null) {
            log.info("找到仓库: {}/{}", ownerName, repositoryName);
            return convertToVO(repository);
        } else {
            log.info("未找到仓库: {}/{}", ownerName, repositoryName);
            return null;
        }
    }

    @Override
    public Boolean updateRepositoryStatistics(String repositoryId) {
        log.info("更新仓库统计信息: repositoryId={}", repositoryId);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }

        try {
            // 检查仓库是否存在
            Repository repository = getById(repositoryId);
            if (repository == null) {
                throw new RuntimeException("仓库不存在: " + repositoryId);
            }

            // 更新最后活动时间
            repository.setLastActivityTime(LocalDateTime.now());
            repository.setUpdateTime(LocalDateTime.now());

            boolean updated = updateById(repository);
            if (updated) {
                log.info("仓库统计信息更新成功: {}", repositoryId);
            } else {
                log.error("仓库统计信息更新失败: {}", repositoryId);
            }

            return updated;
        } catch (Exception e) {
            log.error("更新仓库统计信息时发生错误: repositoryId={}, error={}", repositoryId, e.getMessage(), e);
            throw new RuntimeException("更新仓库统计信息失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Boolean initializeRepository(String repositoryId, Boolean createReadme, Boolean createGitignore,
                                       String gitignoreTemplate, Boolean createLicense, String licenseTemplate) {
        log.info("初始化仓库: repositoryId={}, createReadme={}, createGitignore={}, gitignoreTemplate={}, createLicense={}, licenseTemplate={}",
                repositoryId, createReadme, createGitignore, gitignoreTemplate, createLicense, licenseTemplate);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }

        try {
            // 检查仓库是否存在
            Repository repository = getById(repositoryId);
            if (repository == null) {
                throw new RuntimeException("仓库不存在: " + repositoryId);
            }

            // 设置默认分支（如果没有设置）
            if (repository.getDefaultBranch() == null || repository.getDefaultBranch().trim().isEmpty()) {
                repository.setDefaultBranch("main");
            }

            // 更新仓库状态为已初始化
            repository.setStatus(1); // 1-启用
            repository.setUpdateTime(LocalDateTime.now());

            boolean updated = updateById(repository);

            if (updated) {
                log.info("仓库初始化成功: {}", repositoryId);

                // 这里可以扩展创建初始文件的逻辑
                if (Boolean.TRUE.equals(createReadme)) {
                    log.info("创建README文件: {}", repositoryId);
                    createReadmeFile(repository);
                }

                if (Boolean.TRUE.equals(createGitignore)) {
                    log.info("创建.gitignore文件: {}, 模板: {}", repositoryId, gitignoreTemplate);
                    createGitignoreFile(repository, gitignoreTemplate);
                }

                if (Boolean.TRUE.equals(createLicense)) {
                    log.info("创建LICENSE文件: {}, 许可证: {}", repositoryId, licenseTemplate);
                    createLicenseFile(repository, licenseTemplate);
                }
            } else {
                log.error("仓库初始化失败: {}", repositoryId);
            }

            return updated;
        } catch (Exception e) {
            log.error("初始化仓库时发生错误: repositoryId={}, error={}", repositoryId, e.getMessage(), e);
            throw new RuntimeException("仓库初始化失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String getCloneUrl(String repositoryId, String protocol) {
        log.info("获取克隆URL: repositoryId={}, protocol={}", repositoryId, protocol);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }

        try {
            // 检查仓库是否存在
            Repository repository = getById(repositoryId);
            if (repository == null) {
                throw new RuntimeException("仓库不存在: " + repositoryId);
            }

            // 设置默认协议
            if (protocol == null || protocol.trim().isEmpty()) {
                protocol = "https";
            }

            // 构建克隆URL
            String baseUrl = "git.zenithmind.com"; // 这里应该从配置中获取
            String cloneUrl;

            switch (protocol.toLowerCase()) {
                case "https":
                    cloneUrl = String.format("https://%s/%s/%s.git",
                            baseUrl, repository.getOwnerName(), repository.getName());
                    break;
                case "ssh":
                    cloneUrl = String.format("git@%s:%s/%s.git",
                            baseUrl, repository.getOwnerName(), repository.getName());
                    break;
                case "git":
                    cloneUrl = String.format("git://%s/%s/%s.git",
                            baseUrl, repository.getOwnerName(), repository.getName());
                    break;
                default:
                    throw new IllegalArgumentException("不支持的协议: " + protocol);
            }

            log.info("生成克隆URL: {} -> {}", repositoryId, cloneUrl);
            return cloneUrl;

        } catch (Exception e) {
            log.error("获取克隆URL时发生错误: repositoryId={}, protocol={}, error={}",
                    repositoryId, protocol, e.getMessage(), e);
            throw new RuntimeException("获取克隆URL失败: " + e.getMessage(), e);
        }
    }

    /**
     * 转换为VO
     */
    private RepositoryVO convertToVO(Repository repository) {
        RepositoryVO vo = new RepositoryVO();
        BeanUtils.copyProperties(repository, vo);
        return vo;
    }

    /**
     * 创建README.md文件
     */
    private void createReadmeFile(Repository repository) {
        try {
            String readmeContent = generateReadmeContent(repository);
            log.info("生成README内容完成，仓库: {}, 内容长度: {}", repository.getId(), readmeContent.length());

            // 这里应该调用文件服务创建实际的README.md文件
            // 暂时只记录日志
            log.info("README.md文件创建完成: {}", repository.getName());
        } catch (Exception e) {
            log.error("创建README.md文件失败: {}, 错误: {}", repository.getId(), e.getMessage(), e);
        }
    }

    /**
     * 创建.gitignore文件
     */
    private void createGitignoreFile(Repository repository, String template) {
        try {
            String gitignoreContent = generateGitignoreContent(template);
            log.info("生成.gitignore内容完成，仓库: {}, 模板: {}", repository.getId(), template);

            // 这里应该调用文件服务创建实际的.gitignore文件
            // 暂时只记录日志
            log.info(".gitignore文件创建完成: {}", repository.getName());
        } catch (Exception e) {
            log.error("创建.gitignore文件失败: {}, 错误: {}", repository.getId(), e.getMessage(), e);
        }
    }

    /**
     * 创建LICENSE文件
     */
    private void createLicenseFile(Repository repository, String licenseType) {
        try {
            String licenseContent = generateLicenseContent(licenseType, repository);
            log.info("生成LICENSE内容完成，仓库: {}, 许可证: {}", repository.getId(), licenseType);

            // 这里应该调用文件服务创建实际的LICENSE文件
            // 暂时只记录日志
            log.info("LICENSE文件创建完成: {}", repository.getName());
        } catch (Exception e) {
            log.error("创建LICENSE文件失败: {}, 错误: {}", repository.getId(), e.getMessage(), e);
        }
    }

    /**
     * 生成README内容
     */
    private String generateReadmeContent(Repository repository) {
        StringBuilder content = new StringBuilder();
        content.append("# ").append(repository.getName()).append("\n\n");

        if (repository.getDescription() != null && !repository.getDescription().trim().isEmpty()) {
            content.append(repository.getDescription()).append("\n\n");
        }

        content.append("## 项目介绍\n\n");
        content.append("这是一个由 ").append(repository.getOwnerName()).append(" 创建的项目。\n\n");
        content.append("## 使用说明\n\n");
        content.append("请在此处添加项目的使用说明。\n\n");
        content.append("## 贡献指南\n\n");
        content.append("欢迎提交 Issue 和 Pull Request。\n\n");
        content.append("## 许可证\n\n");
        content.append("请查看 LICENSE 文件了解详情。\n");

        return content.toString();
    }

    /**
     * 生成.gitignore内容
     */
    private String generateGitignoreContent(String template) {
        if (template == null || template.trim().isEmpty()) {
            template = "general";
        }

        StringBuilder content = new StringBuilder();
        content.append("# ").append(template.toUpperCase()).append(" .gitignore\n\n");

        switch (template.toLowerCase()) {
            case "java":
                content.append("*.class\n");
                content.append("*.jar\n");
                content.append("*.war\n");
                content.append("*.ear\n");
                content.append("target/\n");
                content.append(".idea/\n");
                content.append("*.iml\n");
                break;
            case "node":
                content.append("node_modules/\n");
                content.append("npm-debug.log*\n");
                content.append("yarn-debug.log*\n");
                content.append("yarn-error.log*\n");
                content.append(".env\n");
                break;
            case "python":
                content.append("__pycache__/\n");
                content.append("*.py[cod]\n");
                content.append("*$py.class\n");
                content.append("*.so\n");
                content.append(".Python\n");
                content.append("env/\n");
                content.append("venv/\n");
                break;
            default:
                content.append("# 临时文件\n");
                content.append("*.tmp\n");
                content.append("*.temp\n");
                content.append("*.log\n");
                content.append("# 系统文件\n");
                content.append(".DS_Store\n");
                content.append("Thumbs.db\n");
                break;
        }

        return content.toString();
    }

    /**
     * 生成LICENSE内容
     */
    private String generateLicenseContent(String licenseType, Repository repository) {
        if (licenseType == null || licenseType.trim().isEmpty()) {
            licenseType = "MIT";
        }

        StringBuilder content = new StringBuilder();
        String year = String.valueOf(java.time.Year.now().getValue());
        String owner = repository.getOwnerName();

        switch (licenseType.toUpperCase()) {
            case "MIT":
                content.append("MIT License\n\n");
                content.append("Copyright (c) ").append(year).append(" ").append(owner).append("\n\n");
                content.append("Permission is hereby granted, free of charge, to any person obtaining a copy\n");
                content.append("of this software and associated documentation files (the \"Software\"), to deal\n");
                content.append("in the Software without restriction, including without limitation the rights\n");
                content.append("to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n");
                content.append("copies of the Software, and to permit persons to whom the Software is\n");
                content.append("furnished to do so, subject to the following conditions:\n\n");
                content.append("The above copyright notice and this permission notice shall be included in all\n");
                content.append("copies or substantial portions of the Software.\n\n");
                content.append("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n");
                content.append("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n");
                content.append("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n");
                content.append("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n");
                content.append("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n");
                content.append("OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n");
                content.append("SOFTWARE.\n");
                break;
            case "APACHE":
                content.append("Apache License\n");
                content.append("Version 2.0, January 2004\n");
                content.append("http://www.apache.org/licenses/\n\n");
                content.append("Copyright ").append(year).append(" ").append(owner).append("\n\n");
                content.append("Licensed under the Apache License, Version 2.0 (the \"License\");\n");
                content.append("you may not use this file except in compliance with the License.\n");
                content.append("You may obtain a copy of the License at\n\n");
                content.append("    http://www.apache.org/licenses/LICENSE-2.0\n\n");
                content.append("Unless required by applicable law or agreed to in writing, software\n");
                content.append("distributed under the License is distributed on an \"AS IS\" BASIS,\n");
                content.append("WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
                content.append("See the License for the specific language governing permissions and\n");
                content.append("limitations under the License.\n");
                break;
            default:
                content.append("Copyright (c) ").append(year).append(" ").append(owner).append("\n\n");
                content.append("All rights reserved.\n");
                break;
        }

        return content.toString();
    }
}
